/*
@hehung
2023-2-8
转载请注明出处，版权由@hehung所有
email: 1398660197@qq.com
wechat: hehung95
*/

/*******************************************************************************
 * Header Include
 ******************************************************************************/
#include "hal_data.h"
#include "app_hw_i2c.h"
#include "app_hs300x.h"

#define HS300X_DEBUG
#undef HS300X_DEBUG

#ifdef HS300X_DEBUG
#include <stdio.h>
#define LOG(fmt, ...) 	                printf(fmt, ##__VA_ARGS__)
#else
#define LOG(fmt, ...)
#endif 

/*******************************************************************************
 * Macro Definitions
 ******************************************************************************/
#define HS300x_I2C_SLAVE_ADDR_7BIT           (0x44U)

#define HS300X_DATA_VALID                    (0x00U)
#define HS300X_DATA_STALE                    (0x01U)
#define HS300X_STATUS_MASK                   (0xC0000000U)
#define HS300X_STATUS_POS                    (30U)

#define HS300X_DATA_MASK                     (0x3FFFFFFCU)
#define HS300X_HUMI_DATA_MASK                (0x3FFF0000U)
#define HS300X_HUMI_DATA_POS                 (16U)
#define HS300X_TEMP_DATA_MASK                (0x0000FFFCU)
#define HS300X_TEMP_DATA_POS                 (2U)

/* calculation formula, 2^14 - 1 */
#define HS300X_DATA_FACTOR                   (16383U)

/*******************************************************************************
 * Static Variables Definitions 
 ******************************************************************************/
static s_Hs300xDataType hs300x_data;

/*******************************************************************************
 * Static Function Declarations 
 ******************************************************************************/
static void Hs300x_ReadFromI2C(uint8_t *data_buffer, uint8_t data_len);
static void Hs300x_WriteToI2C(uint8_t *data_buffer, uint8_t data_len);
static bool Hs300x_DataConvert(uint32_t read_data, s_Hs300xDataType *cal_result);

/*******************************************************************************
 * Function Definitions 
 ******************************************************************************/
/*********************Hs300x读数据函数************************************/
static void Hs300x_ReadFromI2C(uint8_t *data_buffer, uint8_t data_len)
{
	fsp_err_t err;
	uint32_t timeout_ms = 500;

    // setting mutex for lock sci3_i2c bus
    if (pdTRUE == xSemaphoreTake(mutex_sci3_i2c, portMAX_DELAY))
    {
		R_SCI_I2C_SlaveAddressSet(&g_sci3_i2c_ctrl, 
								HS300x_I2C_SLAVE_ADDR_7BIT, 
								I2C_MASTER_ADDR_MODE_7BIT);

		err = R_SCI_I2C_Read(&g_sci3_i2c_ctrl, data_buffer, data_len, true);
		assert(FSP_SUCCESS == err);
		
		/* Since there is nothing else to do, block until Callback triggers*/
		while ((I2C_MASTER_EVENT_TX_COMPLETE != sci3_i2c_event) && timeout_ms>0)
		{
			R_BSP_SoftwareDelay(1U, BSP_DELAY_UNITS_MICROSECONDS);
			timeout_ms--;
		}
		
		if (I2C_MASTER_EVENT_ABORTED == sci3_i2c_event)
		{
			// __BKPT(0);
			LOG ("Hs300x: sci3 i2c read event aborted occurred\n");
		}
		/* Read data back from the I2C slave */
		sci3_i2c_event = I2C_MASTER_EVENT_ABORTED;

 		// release the mutex, unlock
        (void)xSemaphoreGive(mutex_sci3_i2c);
    }
}

/*********************Hs300x写数据函数************************************/
static void Hs300x_WriteToI2C(uint8_t *data_buffer, uint8_t data_len)
{
	fsp_err_t err;
	uint32_t timeout_ms = 500;

	// setting mutex for lock sci3_i2c bus
    if (pdTRUE == xSemaphoreTake(mutex_sci3_i2c, portMAX_DELAY))
    {
		R_SCI_I2C_SlaveAddressSet(&g_sci3_i2c_ctrl, 
									HS300x_I2C_SLAVE_ADDR_7BIT, 
									I2C_MASTER_ADDR_MODE_7BIT);

		err = R_SCI_I2C_Write(&g_sci3_i2c_ctrl, data_buffer, data_len, true);
		assert(FSP_SUCCESS == err);
		
		/* Since there is nothing else to do, block until Callback triggers*/
		while ((I2C_MASTER_EVENT_TX_COMPLETE != sci3_i2c_event) && timeout_ms>0)
		{
			R_BSP_SoftwareDelay(1U, BSP_DELAY_UNITS_MICROSECONDS);
			timeout_ms--;
		}
		
		if (I2C_MASTER_EVENT_ABORTED == sci3_i2c_event)
		{
			// __BKPT(0);
			LOG ("Hs300x: sci3 i2c write event aborted occurred\n");
		}
		/* Read data back from the I2C slave */
		sci3_i2c_event = I2C_MASTER_EVENT_ABORTED;

 		// release the mutex, unlock
        (void)xSemaphoreGive(mutex_sci3_i2c);
    }
}

static bool Hs300x_DataConvert(uint32_t read_data, s_Hs300xDataType *cal_result)
{
	uint32_t humi_data;
	uint32_t temp_data;
	
    if (((read_data & HS300X_STATUS_MASK) >> HS300X_STATUS_POS) == HS300X_DATA_VALID)
	{
		// Data is valid
		humi_data = (read_data & HS300X_HUMI_DATA_MASK) >> HS300X_HUMI_DATA_POS;
		temp_data = (read_data & HS300X_TEMP_DATA_MASK) >> HS300X_TEMP_DATA_POS;

		// Calculate the humidity: humi_data/(2^14-1) * 100
		cal_result->humi = (double)humi_data/(double)(HS300X_DATA_FACTOR) * 100.0;
		// Calculate the temperature: temp_data/(2^14-1) * 165 - 40
		cal_result->temp = (double)temp_data/(double)(HS300X_DATA_FACTOR) * 165.0 - 40;
#ifdef HS300X_DEBUG
		LOG("humidity:%f, temperature:%f\n", cal_result->humi, cal_result->temp);
#endif
		
		return true;
	}
	else
	{
		return false;
	}
}

void Hs300x_Init(void)
{
    // Do not settings, keep default settings in sensor device
}

void Hs300x_StartSampling(void)
{
    uint8_t data[4];
	uint32_t data_u32;
	
	// Write address start measurement
    Hs300x_WriteToI2C(NULL, 0);
	// Delay 50ms to waiting for convert finished
	DELAY_MS(50);
	// Read measurement result from sensor HS300X
	Hs300x_ReadFromI2C(data, 4);
	// Convert the data to 32bits
	data_u32 = (uint32_t)((data[0] << 24U) | 
	                      (data[1] << 16U) | 
	                      (data[2] << 8U) | 
	                      (data[3]));
	// Read the temperature and humidity
	(void)Hs300x_DataConvert(data_u32, &hs300x_data);
	
#ifdef HS300X_DEBUG
	LOG("HS300X origin data1:%x%x%x%x\n", data[0],data[1],data[2],data[3]);
	// LOG("HS300X origin data2:%x\n", data_u32);
#endif
}


s_Hs300xDataType Hs300x_ReadData(void)
{
	return hs300x_data;
}

